#include "regbase.h"

#include "iot_debug.h"
#include "idevice.h"
#include "util_tools.h"
#include "config.h"

#include <limits.h>
#include <sstream>
#include <logger.h>

RegBase::RegBase(const std::string &name) :
    enabled(false),
    name_(name),
    reg_status_(INIT),
    transfer_reg_status_(INIT)
{

}

RegBase::~RegBase()
{

}

bool RegBase::fillData(const uint8_t *data, uint32_t len, IDevice *dev, bool dump)
{
    if (dump)
        printf("dev:%s  ", dev->devName().c_str());

    if (rawDataType() == TYPE_BIT1)
    {
        setRawData((data[0] & 0x01)?true:false);

        if (dump)
            printf("%s:%s  ", name().c_str(), actived() ? toString().c_str() : "inactived");
    }
    else if (rawDataType() == TYPE_STR || rawDataType() == TYPE_STRING)
    {
        setRawData(std::string((const char *)data, len));
        if (dump)
            printf("%s:%s  ", name().c_str(), actived() ? toString().c_str():"inactived");
    }
    else
    {
        setRawData(data);
        if (dump)
            printf("%s:%s  ", name().c_str(), actived() ? toString().c_str():"inactived");
    }

    if (dump)
        printf("\n");

    return true;
}

RegBase *findReg(RegInfos &regs, const std::string &name)
{
    for (RegInfos::iterator inf=regs.begin(); inf!=regs.end(); inf++) {
        RegBase *reg = *inf;
        if (reg->name() == name)
            return reg;
    }
    return nullptr;
}

const RegBase *findReg(const RegInfos &regs, const std::string &name)
{
    for (RegInfos::const_iterator inf=regs.begin(); inf!=regs.end(); inf++) {
        const RegBase *reg = *inf;
        if (reg->name() == name)
            return reg;
    }
    return nullptr;
}



bool RegInfos::check(time_t tm)
{
    return checkTime(this->tm, tm, this->polling_cycle);
}

bool RegInfos::fillData(const uint8_t *data, uint32_t len, IDevice *dev, bool dump)
{
    if (dump)
        printf("dev:%s  ", dev->devName().c_str());

    uint8_t pos = 0;
    int bit = 0;

    for (RegInfos::iterator it=this->begin(); it!=this->end(); it++)
    {
        RegBase * reg = *it;
        if (reg->rawDataType() == TYPE_BIT1)
        {
            reg->setRawData((data[pos]&(1<<bit))?true:false);

            if (dump)
                printf("%s:%s  ", reg->name().c_str(), reg->actived()?reg->toString().c_str():"inactived");

            bit++;
            if (bit == 8)
            {
                bit = 0;
                pos++;
            }
        }
        else if (reg->rawDataType() == TYPE_STR || reg->rawDataType() == TYPE_STRING)
        {
            reg->setRawData(std::string((const char *)data, len));
            if (dump)
                printf("%s:%s  ", reg->name().c_str(), reg->actived() ? reg->toString().c_str():"inactived");
        }
        else
        {
            if (bit) pos++;
            bit = 0;
            pos += reg->setRawData(data+pos);
            if (dump)
                printf("%s:%s  ", reg->name().c_str(), reg->actived()?reg->toString().c_str():"inactived");
        }
    }

    if (dump)
        printf("\n");

    return true;
}

RegInfos::iterator RegInfos::operator[](uint32_t item)
{
    if (item >= this->size())
        return this->end();

    iterator it=this->begin();
    while(item--)
        it++;

    return it;
}
